// 利用图可视化引擎-G6（https://g6.antv.antgroup.com/manual/introduction），开发网络拓扑
<template>
  <div class="g6-wrap h-100">
    <div :id="id" :ref="id" class="h-100" />
  </div>
</template>

<script>
  import { mapGetters } from 'vuex'
  import { deepClone } from '@/utils/common'
  import RenderG6 from './js/G6'
  import { colorData, categoryNode, nodeColor, edgeColor } from '@/views/module/home/components/vis/js/format.js'
  export default {
    props: {
      id: {
        type: String,
        default: 'g6-container'
      },
      nodes: {
        type: Array,
        default: () => []
      },
      edges: {
        type: Array,
        default: () => []
      },
      btnIn: {
        type: Boolean,
        default: true
      },
      isEdit: {
        type: Boolean,
        default: false
      },
      fullScreen: {
        type: Boolean,
        default: false
      }
    },
    data() {
      return {
        G6: null,
        graph: null,
        graphOffsetTop: 0,
        mouseEvent: '',
        cloneNodes: []
      }
    },
    computed: {
      ...mapGetters([
        'dictCableLevelList',
        'gisActived',
        'stationSelected',
        'cableLevelSelected',
        'hideAlarmLevel'
      ]),
      dictCableLevelList() {
        return this.customDictList.filter(i => i.type === 'CABLE_LEVEL')
      }
    },
    watch: {
      nodes: {
        handler(newVal, oldVal) {
          console.log('点击了刷新', newVal)
          this.cloneNodes = deepClone(this.nodes)
          this.clearState()
          this.renderTopo()
        }
      },
      btnIn: {
        handler(newVal) {
          console.log(`鼠标${newVal ? '进入' : '离开'}按钮列表`)
          if (!newVal) {
            this.clearState()
          }
        }
      },
      isEdit: {
        handler(newVal, oldVal) {
          console.log(newVal ? '编辑' : '退出编辑')
          this.clearState()
          this.setEditable(newVal)
          if (newVal !== oldVal && !newVal) {
            this.renderTopo()
          }
        }
      },
      gisActived(newVal, oldVal) {
        console.log('高亮状态改变', newVal)
        this.highLightTopo()
        // this.G6.motoTo(newVal.nodeIds)
      },
      stationSelected() {
        console.log('站点筛选', this.stationSelected)
        this.clearState()
        this.renderTopo()
      },
      cableLevelSelected() {
        console.log('光缆', this.cableLevelSelected)
        this.clearState()
      },
      hideAlarmLevel() {
        console.log('告警等级过滤', this.hideAlarmLevel)
        if (this.isEdit) return
        this.renderTopo()
      }
    },
    mounted() {
      this.$nextTick(() => {
        this.init()
        this.cloneNodes = deepClone(this.nodes)
        this.renderTopo(true)
      })
    },
    beforeDestroy() {
      if (this.G6) {
        this.G6.clear()
      }
    },
    methods: {
      init() {
        const g6Container = document.getElementById(this.id)
        if (!g6Container) return

        this.G6 = new RenderG6()
        this.G6.init({
          container: g6Container,
          width: g6Container.scrollWidth,
          height: g6Container.scrollHeight,
          showMiniMap: true
        })
        this.graph = this.G6.graph
        this.addEvent()
      },
      renderTopo(fitView = false) {
        const stationData = []
        const visiableStationIds = []
        const ishighLight = this.gisActived.filterType !== 'CABLE'
        this.cloneNodes.forEach(i => {
          if (this.stationSelected.includes(i.nodeId)) {
            visiableStationIds.push(i.nodeId)
            let highLight = ''
            let color = null
            // 站点高亮
            if (this.gisActived.nodeIds.includes(i.nodeId)) {
              i.highLight = ishighLight// 标识站点高亮
              highLight = ishighLight ? 'highLight' : ''
              color = this.gisActived.color || nodeColor(i)
              i.image = categoryNode(i, highLight)
              i.font = {
                color: colorData[color] || nodeColor(i)
              }
            } else {
              // 重置为初始状态
              i.image = categoryNode(i)
              i.font = {
                color: nodeColor(i)
              }
            }
            stationData.push(i)
          }
        })
        const lineData = []
        this.edges.forEach(i => {
          if (
            visiableStationIds.includes(i.fromNodeId) &&
            visiableStationIds.includes(i.toNodeId) &&
            this.cableLevelSelected.includes(i.cableLevel)
          ) {
            let color = null
            if (this.gisActived.cableIds.includes(i.cableId)) {
              color = this.gisActived.color
              i.font = {
                color: colorData[color],
                size: 16
              }
              i.color = {
                color: colorData[color],
                opacity: 1
              }
              i.width = 4
              i.highLight = true
            } else {
              // 重置为初始状态
              color = edgeColor(i)
              i.font = {
                color: color,
                size: 0
              }
              i.color = {
                color: color,
                opacity: 0.5
              }
              i.width = 2
            }
            lineData.push(i)
          }
        })
        this.G6.update({
          nodes: stationData,
          edges: lineData
        }, fitView)
      },
      highLightTopo() {
        const color = this.gisActived.color
        this.graph.getNodes().forEach(node => {
          const nodeData = node.getModel()
          if (nodeData.highLight) {
            // 重置为初始状态
            this.graph.updateItem(node, {
              img: categoryNode(nodeData),
              labelCfg: {
                style: {
                  fill: nodeColor(nodeData)
                }
              },
              highLight: false
            })
          }
          // 站点高亮
          if (this.gisActived.nodeIds.includes(nodeData.nodeId)) {
            const highLight = this.gisActived.filterType !== 'CABLE' // 如果是光缆筛选不需要高亮站点
            this.graph.updateItem(node, {
              img: categoryNode(nodeData, highLight ? 'highLight' : ''),
              labelCfg: {
                style: {
                  fill: colorData[color || nodeColor(nodeData)]
                }
              },
              highLight: highLight
            })
          }
        })
        this.graph.getEdges().forEach(edge => {
          const edgeData = edge.getModel()
          const defaultColor = edgeColor(edgeData)
          if (edgeData.highLight) {
            // 重置为初始状态
            edge.update({
              ...edgeData,
              style: {
                stroke: defaultColor,
                strokeOpacity: 0.5,
                lineWidth: 2
              },
              labelCfg: {
                style: {
                  fill: defaultColor,
                  opacity: 0,
                  size: 16
                }
              },
              highLight: false
            })
          }
          if (this.gisActived.cableIds.includes(edgeData.cableId)) {
            edge.update({
              ...edgeData,
              style: {
                stroke: colorData[color],
                strokeOpacity: 1,
                lineWidth: 4
              },
              labelCfg: {
                refY: 30,
                autoRotate: true,
                style: {
                  fill: colorData[color],
                  opacity: 1,
                  size: 16
                }
              },
              highLight: true
            })
          }
        })
      },
      fitView() {
        console.log('走这个了')
        const g6WrapWH = document.querySelector('.g6-wrap').getBoundingClientRect()
        if (this.graph) {
          this.graph.changeSize(Math.floor(g6WrapWH.width), Math.floor(g6WrapWH.height))
          this.graph.fitView()
        }
      },
      setEditable(newVal) {
        this.graph && this.graph.setMode(newVal ? 'edit' : 'default')
      },
      cancelEdit() {
        this.cloneNodes = deepClone(this.nodes) // 取消编辑但是没保存就需要恢复原来的位置
      },
      addEvent() {
        const mainBox = document.querySelector('#mapContainer').getBoundingClientRect()
        const left = mainBox.left
        const top = mainBox.top
        this.graph.on('node:click', evt => {
          // console.log('选中节点', evt)
          if (this.isEdit) return
          const nodeItem = evt.item
          const model = nodeItem.getModel()
          this.mouseEvent = 'stationClick'
          this.$emit('selectNode', {
            ...model,
            type: model.itemType,
            mouseEvent: 'stationClick',
            mouseStatus: 'SELECT',
            left: evt.clientX - left,
            top: evt.clientY - top
          })
        })
        this.graph.on('node:mouseenter', evt => {
          // console.log('节点移入', evt)
          if (this.isEdit) return
          const nodeItem = evt.item
          const model = nodeItem.getModel()
          if (this.curNode && model.id !== this.curNode.id) {
            this.mouseEvent = 'stationHover'
          }
          this.curNode = model
          if (this.mouseEvent !== 'stationClick') {
            this.$emit('hoverNode', {
              ...model,
              clickProp: 'hoverNode',
              mouseStatus: 'HOVER',
              mouseEvent: 'stationHover',
              left: evt.clientX - left + 10,
              top: evt.clientY - top + 10
            })
          }
        })
        this.graph.on('node:mouseleave', evt => {
          // console.log('节点移出', evt)
          if (this.isEdit) return
          const nodeItem = evt.item
          const model = nodeItem.getModel()
          if (this.mouseEvent !== 'stationClick') {
            this.$emit('hoverNode', {
              ...model,
              mouseStatus: 'LEAVE',
              mouseEvent: '',
              left: 0,
              top: 0
            })
          }
        })
        this.graph.on('node:dragstart', evt => {
          this.clearState()
        })
        this.graph.on('node:dragend', evt => {
          console.log('节点拖拽结束')
          const node = evt.item
          const model = node.getModel()
          const nodeData = this.G6.nodes.find(i => i.id === model.id) // 同时需要改变数据源里的数据
          nodeData.x = model.x
          nodeData.y = model.y
        })
        this.graph.on('combo:dragend', evt => {
          console.log('组拖拽结束')
          const combo = evt.item
          combo.getNodes().forEach(i => {
            const model = i.getModel()
            const nodeData = this.G6.nodes.find(j => j.id === model.id) // 同时需要改变数据源里的数据
            nodeData.x = model.x
            nodeData.y = model.y
          })
        })
        this.graph.on('edge:click', evt => {
          // console.log('选中边', evt)
          if (this.isEdit) return
          const nodeItem = evt.item
          const model = nodeItem.getModel()
          this.mouseEvent = 'fiberClick'
          this.$emit('selectEdge', {
            id: model.id,
            mouseStatus: 'SELECT',
            mouseEvent: 'fiberClick',
            label: model.label,
            left: evt.clientX - left,
            top: evt.clientY - top,
            fromNodeId: model.fromNodeId,
            toNodeId: model.toNodeId,
            cableId: model.cableId
          })
        })
        this.graph.on('edge:mouseenter', evt => {
          // console.log('边移入', evt)
          if (this.isEdit) return
          const edgeItem = evt.item
          const model = edgeItem.getModel()
          edgeItem.update({ style: {
            lineWidth: 6,
            stroke: model.color.color
          }, labelCfg: {
            refY: 30,
            autoRotate: true,
            style: { opacity: 1 }
          }})
          this.mouseEvent = 'fiberHover'
          if (this.mouseEvent !== 'fiberClick') {
            this.$emit('hoverEdge', {
              id: model.id,
              mouseStatus: 'HOVER',
              mouseEvent: 'fiberHover',
              left: evt.clientX - left + 10,
              top: evt.clientY - top + 10
            })
          }
        })
        this.graph.on('edge:mouseleave', evt => {
          // console.log('边移出', evt)
          if (this.isEdit) return
          const edgeItem = evt.item
          const model = edgeItem.getModel()
          edgeItem.update({ style: {
            lineWidth: model.width,
            stroke: model.color.color
          }, labelCfg: {
            style: { opacity: 0 }
          }})
          if (this.mouseEvent !== 'fiberClick') {
            this.$emit('hoverEdge', {
              id: model.id,
              mouseStatus: 'LEAVE',
              mouseEvent: ''
            })
          }
        })
        this.graph.on('canvas:click', evt => {
          this.clearState()
        })
        this.graph.on('canvas:dragstart', evt => {
          this.clearState()
        })
      },
      // 清除状态，比如悬浮，选中状态等
      clearState() {
        this.mouseEvent = ''
        this.$emit('dragStart') // 把按钮弹窗隐藏
        if (this.gisActived.nodeIds.length || this.gisActived.cableIds.length) {
          this.$store.commit('setGisActived', { // 取消高亮
            cableIds: [],
            nodeIds: [],
            color: ''
          })
        }
        this.$emit('hoverEdge', {
          mouseStatus: 'LEAVE',
          mouseEvent: '',
          left: 0,
          top: 0
        })
      },
      autoLayout() {
        this.G6 && this.G6.adjustXY()
      }
    }
  }
</script>
<style lang="scss">
@import '@/assets/css/mixin.module.scss';
.g6-wrap {
  overflow: hidden;
}
.minimap {
  position: fixed;
  bottom: 15px;
  right: 10px;
  @include themeify {
    border: 1px solid themed('bigBorderColor');
  }
}
</style>
